package com.dearbinge.pay.util;


import java.io.IOException;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.SortedMap;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.jdom2.JDOMException;

import com.dearbinge.pay.util.wxsdk.Digests;
import com.dearbinge.pay.util.wxsdk.XMLUtil;
import com.dearbinge.utils.Constants;
import com.google.common.collect.Maps;

/**
 * @ClassName: WxpayUtil
 * @author: SuperZemo
 * @email: zemochen@gmail.com
 * @Date 6/26/15 14:27
 * @Description 微信支付工具
 */
public class WxpayUtil {

    private static final String UNIFIED_ORDER = "https://api.mch.weixin.qq.com/pay/unifiedorder";//统一下单
    private static final String ORDER_QUERY = "https://api.mch.weixin.qq.com/pay/orderquery";//查询订单
    private static final String CLOSE_ORDER = "https://api.mch.weixin.qq.com/pay/closeorder";//关闭订单
    private static final String PAY_REFUND = "https://api.mch.weixin.qq.com/secapi/pay/refund";//申请退款
    private static final String STATUS_SUCCESS = "success";


//    private static  String APP_ID = "wx69af5446bd66d789";
//    private static  String MCH_ID = "1511744041"; //商户号
//    private static  String APP_KEY = "76ea2a0974bb247155e1ca3c753249b7";


//    private static final String ENV = "dev";    //开发环境,dev时支付金额不乘以100

    /**
     * 查询订单
     * @param transactionId
     * @param outTradeNo
     * @param fee
     * @return
     */
    public static boolean verifyOrder(String transactionId, String outTradeNo, Double fee) {
        //组装请求查询订单所需参数
        SortedMap<String, String> map = Maps.newTreeMap();
        map.put("appid", Constants.appid);
        map.put("mch_id", Constants.mch_id);
        map.put("nonce_str", genNonceStr());
        if (StringUtils.isNotBlank(transactionId)) {
            map.put("transaction_id", transactionId);
        } else {
            map.put("out_trade_no", outTradeNo);

        }
        map.put("sign", createSign(map));
        //建立连接查询
        String xmlString = buildXML(map);
        HttpClient client = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(ORDER_QUERY);
        try {
            httpPost.setEntity(new StringEntity(xmlString, "UTF-8"));

            HttpResponse resp = client.execute(httpPost);
            if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                return false;
            }
            HttpEntity entity = resp.getEntity();
            String result = EntityUtils.toString(entity, "UTF-8");
            result = result.replace("<![CDATA[", "").replace("]]>", "");
            //获取查询结果
            Map<String, String> param = XMLUtil.doXMLParse(result);
            String returnCode = param.get("return_code");
            String resultCode = param.get("result_code");
            String billNo = param.get("out_trade_no");
            //判断查询真实性，防止钓鱼攻击
            if (resultCode.equalsIgnoreCase(STATUS_SUCCESS) &&returnCode.equalsIgnoreCase(STATUS_SUCCESS) && outTradeNo.equals(billNo)) {
                Double totalFee = Double.valueOf(param.get("total_fee")) ;
                if (totalFee.equals(fee)) {
                    return true;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
    * 微信回调接口
    */
    private static String NOTIFY_URL = "";
    public static final String PAY_TYPE_JSAPI = "JSAPI";
    public static final String PAY_TYPE_APP = "APP";
    /**
     * 调用微信的app支付
     * @param orders
     * @param paymentParam
     * @return
     */
//    public static String payment(Orders orders,String ip, PaymentParamBean paymentParam) {
//
//    	//设置微信回调地址
//        NOTIFY_URL = Configure.getValue("wechat.notify_url");
//        APP_ID = paymentParam.getWechatAppId();
//        MCH_ID = paymentParam.getWechatAppKey();
//        APP_KEY = paymentParam.getWechatMchId();
//
//        String noncestr = genNonceStr();
//        Double totalAmount = orders.getOrderTotalAmount();
//        System.out.println(totalAmount);
//        //把订单数据封装到map中
//        SortedMap<String, String> map = buildPrePayParam(orders.getOrderSetCount(), totalAmount, orders.getOrderNo(), PAY_TYPE_APP,ip,noncestr);
//        //访问微信的得到   prepay_id
//        String packageString = getPerPayId(map);
//        System.out.println("PerPayId----"+packageString);
//        //二次签名准备返回
//        Map<String, String> packageValue = createPackageValue(packageString,noncestr);
//        packageValue.remove("package");
//        JSONArray jsonArray = JSONArray.fromObject(packageValue);
//        return jsonArray.toString().replace("[", "").replace("]","" );
//    }

//    public static String payment(Order orders,String ip) {
//        String noncestr = genNonceStr();
//        //把订单数据封装到map中
//        SortedMap<String, String> map = buildPrePayParam(orders.getOrderSetCount(), orders.getPayment(), orders.getOrderId(), PAY_TYPE_APP,ip,noncestr);
//        //访问微信的得到   prepay_id
//        String packageString = getPerPayId(map);
//        //二次签名准备返回
//        Map<String, String> packageValue = createPackageValue(packageString,noncestr);
//        packageValue.remove("package");
//        JSONArray jsonArray = JSONArray.fromObject(packageValue);
//        return jsonArray.toString().replace("[", "").replace("]","" );
//    }


    /**
     * 封装到map中
     * @param body
     * @param price
     * @param tradeNo
     * @param type
     * @param ip
     * @return
     */
    public static SortedMap<String, String> buildPrePayParam(String body, double price, String tradeNo, String type,String ip,String noncestr) {
        SortedMap<String, String> info = Maps.newTreeMap();
        //设置package订单参数
        info.put("appid", Constants.appid);
        //商户号
        info.put("mch_id", Constants.mch_id);
        info.put("nonce_str", noncestr);
        //商品描述
        info.put("body", body);
        //商家订单号
        info.put("out_trade_no", tradeNo);
        //商品金额,以"分"为单位
//        if (!"dev".equals(ENV)) {
//            price = (price * 100);
//        }
        price = (price * 100);
//        price = (0.01 * 100);
        info.put("total_fee", (int) Math.abs(price) + "");
        //订单生成的机器IP，指用户浏览器端IP
        info.put("spbill_create_ip", ip);
        //支付类型
        info.put("trade_type", type);
        //异步回调url
        info.put("notify_url", NOTIFY_URL);
        return info;
    }
    /**
     * 生成随机数
     *
     * @return
     */
    public static String genNonceStr() {
        Random random = new Random();
        return Digests.MD5(String.valueOf(random.nextInt(10000)));
    }
    /**
     * 根据key获取xml值
     *
     * @param result
     * @param key
     * @return
     */
    private static String getXMLValue(HttpEntity result, String key) {
        //获取查询结果
        try {
            String resource = EntityUtils.toString(result, "UTF-8");
            System.out.println("-----------resource---"+resource);
            resource = resource.replace("<![CDATA[", "").replace("]]>", "");
            Map<String, String> param = XMLUtil.doXMLParse(resource);
            System.out.println(resource);
            //System.out.println(param.get(key));

            return param.get(key);
        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 获取时间戳
     *
     * @return
     */
    public static String getTimestamp() {
        return Long.toString(new Date().getTime() / 1000);
    }
    /**
     * 生成预支付订单
     *
     * @return
     */
    public static String getPerPayId(SortedMap<String, String> map) {
        String xml = getPackageSign(map);
        System.out.println("-----xml------"+xml);
        HttpClient client = new DefaultHttpClient();
        System.out.println("-----client------"+client);
        HttpPost httpPost = new HttpPost(UNIFIED_ORDER);
        System.out.println("-----httpPost------"+httpPost);
        try {
            httpPost.setEntity(new StringEntity(xml, "UTF-8"));
            HttpResponse resp = client.execute(httpPost);
            System.out.println("-----resp------"+resp);
            HttpEntity entity = resp.getEntity();
            System.out.println("-----entity------"+entity);
            if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                return null;
            }
            return getXMLValue(entity, "prepay_id");
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }







    /**
     * 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
     */
    public static String createSign(SortedMap<String, String> packageParams) {
        StringBuffer sb = new StringBuffer();
        Set es = packageParams.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            String v = (String) entry.getValue();
            if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + Constants.key);
        String sign = Digests.MD5(sb.toString()).toUpperCase();
        return sign;
    }
    /**
     * 一次签名加构建XML
     * @param map
     * @return
     */
    private static String getPackageSign(SortedMap<String, String> map) {

        map.put("sign", createSign(map));
        return buildXML(map);
    }
    /**
     * 二次签名
     * @param prepayid
     * @return
     */
    public static Map<String, String> createPackageValue(String prepayid,String noncestr) {
        SortedMap<String, String> map = Maps.newTreeMap();
        //设置package订单参数
        //appid，partnerid，prepayid，noncestr，timestamp，package
        map.put("appid", Constants.appid);
        map.put("partnerid", Constants.mch_id);
        map.put("prepayid", prepayid);
        map.put("noncestr", noncestr);
        map.put("timestamp", getTimestamp());
        map.put("package", "Sign=WXPay");
        map.put("sign", createSign(map));
        return map;
    }
    /**
     * map转换xml
     * @return
     */
    public static String conversionXML(SortedMap<String,String> map){
        StringBuilder xml = new StringBuilder();
        xml.append("<xml>\n");
        for (Map.Entry<String, String> entry : map.entrySet()) {
            if ("return_code".equals(entry.getKey()) || "return_msg".equals(entry.getKey())) {
                xml.append("<" + entry.getKey() + "><![CDATA[").append(entry.getValue()).append("]]></" + entry.getKey() + ">\n");
            } else {
                xml.append("<" + entry.getKey() + ">").append(entry.getValue()).append("</" + entry.getKey() + ">\n");
            }
        }

        xml.append("</xml>");
        return xml.toString();
    }
    /**
     * 构建xml
     *
     * @param map
     * @return
     */
    private static String buildXML(SortedMap<String, String> map) {
        StringBuilder xml = new StringBuilder();
        xml.append("<xml>\n");
        for (Map.Entry<String, String> entry : map.entrySet()) {
            if ("body".equals(entry.getKey()) || "sign".equals(entry.getKey())) {
                xml.append("<" + entry.getKey() + "><![CDATA[").append(entry.getValue()).append("]]></" + entry.getKey() + ">\n");
            } else {
                xml.append("<" + entry.getKey() + ">").append(entry.getValue()).append("</" + entry.getKey() + ">\n");
            }
        }

        xml.append("</xml>");
        return xml.toString();
    }






























    /**
     * 关闭订单
     * 以下情况需要调用关单接口：商户订单支付失败需要生成新单号重新发起支付，要对原订单号调用关单，避免重复支付；系统下单后，用户支付超时，系统退出不再受理，避免用户继续，请调用关单接口。
     *
     * @param tradeNo 系统内订单号
     * @return
     */
//    public static boolean closeOrder(String tradeNo) {
//        SortedMap<String, String> map = Maps.newTreeMap();
//        map.put("appid", APP_ID);
//        //商户号
//        map.put("mch_id", MCH_ID);
//        map.put("nonce_str", genNonceStr());
//        //商家订单号
//        map.put("out_trade_no", tradeNo);
//        String xml = getPackageSign(map);
//        HttpClient client = new DefaultHttpClient();
//        HttpPost httpPost = new HttpPost(CLOSE_ORDER);
//        try {
//            httpPost.setEntity(new StringEntity(xml, "UTF-8"));
//            HttpResponse resp = client.execute(httpPost);
//            HttpEntity entity = resp.getEntity();
//            if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
//                return false;
//            }
//            return getXMLValue(entity, "return_code").equals("SUCCESS") ? true : false;
//        } catch (IOException e) {
//            e.printStackTrace();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return false;
//    }

    /**
     * 退款
     * @return
     */
//    public static Boolean refund(String tradeNo, int totalFee, int refundFee) {
//        SortedMap<String, String> map = Maps.newTreeMap();
//        map.put("appid", APP_ID);
//        //商户号
//        map.put("mch_id", MCH_ID);
//        map.put("nonce_str", genNonceStr());
//        //商家订单号
//        map.put("out_trade_no", tradeNo);
//        //商户系统内部的退款单号,暂用订单号,同一个单号只能退款一次
//        map.put("out_refund_no", tradeNo);
//        //订单总额
//        map.put("total_fee", totalFee + "");
//        //退款金额
//        map.put("refund_fee", refundFee + "");
//        //操作员
//        map.put("op_user_id", MCH_ID);
//        String xml = getPackageSign(map);
//        HttpClient client = new DefaultHttpClient();
//        HttpPost httpPost = new HttpPost(PAY_REFUND);
//        SSLContext sslContext = null;
//        try {
//
//            KeyStore ks = KeyStore.getInstance("pkcs12");
//            InputStream ins = WxpayUtil.class.getResourceAsStream("/cert/apiclient_cert.p12");
//            ks.load(ins, MCH_ID.toCharArray());
//
//            SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(ks, MCH_ID.toCharArray()).build();
//            // Allow TLSv1 protocol only
//            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null,
//                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
//            client = HttpClients.custom().setSSLSocketFactory(sslsf).build();
//            httpPost.setEntity(new StringEntity(xml, "UTF-8"));
//            HttpResponse resp = client.execute(httpPost);
//            HttpEntity entity = resp.getEntity();
//            if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
//                return false;
//            }
//            return getXMLValue(entity, "return_code").equals("SUCCESS") ? true : false;
//        } catch (IOException e) {
//            e.printStackTrace();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return false;
//    }


}
